﻿using Newtonsoft.Json;
using Surging.Core.CPlatform.Transport.Implementation;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Surging.Core.ProxyGenerator
{
    /// <summary>
    /// dora自己的服务代理生成器
    /// </summary>
    public class DoraProxyServiceBase : ProxyServiceBase
    {

        public DoraProxyServiceBase()
        {
        }

        public RpcContext Context => RpcContext.GetContext();
        private IServiceProxyProvider _remoteServiceProxy;
        public object GetParam(string key) => Context.GetAttachment(key);
        public string Token
        {
            get
            {
                //return RpcContext.GetContext().GetAttachment("token")?.ToString();
                object objToken;
                var contextParams = RpcContext.GetContext().GetContextParameters();

                contextParams.TryGetValue("token", out objToken);
                return objToken?.ToString();
            }
        }
        public string ClientIp
        {
            get
            {
                //return RpcContext.GetContext().GetAttachment("ip")?.ToString();
                object objIP;
                var contextParams = RpcContext.GetContext().GetContextParameters();

                contextParams.TryGetValue("ip", out objIP);
                return objIP?.ToString();
            }
        }

        public Task<T> RemoteInvoke<T>(string routePath, dynamic param)
        {
            return RemoteInvoke<T>(routePath, param, "");
        }

        public async Task<T> RemoteInvoke<T>(string routePath, dynamic param, string serviceKey)
        {
            _remoteServiceProxy = GetService<IServiceProxyProvider>();

            object remoteInvokeResult;
            var dic = new Dictionary<string, object>();

            if (param != null)
            {
                Type t = param.GetType();
                // 获取类的所有公共属性
                var pInfo = t.GetProperties();
                foreach (var pio in pInfo)
                {
                    var pValue = pio.GetValue(param, null);
                    if (pValue==null)
                    {
                        Console.WriteLine($@"key{pio.Name}=value{pValue}");

                    }

                    if (dic.TryAdd(pio.Name, pValue))
                    {
                    }
                    else
                    {
                        Console.WriteLine($@"key{pio.Name}=value{pValue}");
                    }
                }
            }

            try
            {
                if (string.IsNullOrWhiteSpace(serviceKey))
                {
                    remoteInvokeResult = await _remoteServiceProxy.Invoke<object>(dic, routePath);
                }
                else
                {
                    remoteInvokeResult = await _remoteServiceProxy.Invoke<object>(dic, routePath, serviceKey);
                }

            }
            catch (Exception ex)
            {
                Console.WriteLine($"远程调用error,url={routePath},ex.Message={ex.Message} ex.StackTrace={ex.StackTrace}");
                throw;
            }
            if (remoteInvokeResult == null || remoteInvokeResult.Equals("null") || string.IsNullOrWhiteSpace(remoteInvokeResult.ToString()))
            {
                Console.WriteLine($"远程调用结果为null,url={routePath}");
                return default(T);
            }

            if (remoteInvokeResult.GetType().IsValueType)
            {
                //return (T)remoteInvokeResult;
                return (T)Convert.ChangeType(remoteInvokeResult, typeof(T));
            }
            else if (typeof(T) == typeof(string))
            {
                return (T)remoteInvokeResult;
            }
            else
            {
                try
                {
                    var result = JsonConvert.DeserializeObject<T>(remoteInvokeResult.ToString());


                    return result;
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    //throw;
                }

                return default(T);
            }
        }
        public static string GetName<T>(T item) where T : class
        {
            return typeof(T).GetProperties()[0].Name;
        }
    }

    public static class MemberInfoGetting
    {
        public static string GetMemberName<T>(Expression<Func<T>> memberExpression)
        {
            MemberExpression expressionBody = (MemberExpression)memberExpression.Body;
            return expressionBody.Member.Name;
        }

        /// <summary>
        /// 获取变量名称
        /// </summary>
        /// <param name="exp"></param>
        /// <returns>return string</returns>
        public static string GetVarName<T>(System.Linq.Expressions.Expression<Func<T, T>> exp)
        {
            return ((System.Linq.Expressions.MemberExpression)exp.Body).Member.Name;
        }
    }
}
